package cn.com.idmy.auth.interceptor;

import cn.com.idmy.auth.login.LoginManager;
import cn.com.idmy.auth.rbac.RbacManager;
import cn.com.idmy.auth.router.StopMatchException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.Setter;
import lombok.experimental.Accessors;
import org.jetbrains.annotations.NotNull;
import org.springframework.web.method.HandlerMethod;

import java.lang.reflect.Method;
import java.util.function.Consumer;

@Accessors(fluent = true)
public class RbacInterceptor<ID> extends AuthInterceptor {
    protected final LoginManager<ID> loginManager;
    protected final RbacManager<ID> rbacManager;
    @Setter
    protected boolean rbacEnabled = true;

    public RbacInterceptor(Consumer<Object> auth, LoginManager<ID> loginManager, RbacManager<ID> rbacManager) {
        super(auth);
        this.loginManager = loginManager;
        this.rbacManager = rbacManager;
    }

    @Override
    public boolean preHandle(@NotNull HttpServletRequest request, @NotNull HttpServletResponse response, @NotNull Object handler) {
        if (handler instanceof HandlerMethod method && hasAuthWhitelist(method.getMethod())) {
            return true;
        }

        try {
            auth.accept(handler);
        } catch (StopMatchException ignored) {
        }

        if (rbacEnabled && handler instanceof HandlerMethod handlerMethod) {
            checkRbac(handlerMethod.getMethod());
        }
        return true;
    }

    protected void checkRbac(Method m) {
        var id = loginManager.idNullable();
        if (id != null) {
            rbacManager.check(id, m);
        }
    }
}
